// <com.woyouqiu.Copyright>
// --------------------------------------------------------------
// <copyright>上海有求网络科技有限公司 2015</copyright>
// <Solution>Vecen.BangChuang</Solution>
// <Project>Vecen.BangChuang.Core</Project>
// <FileName>PingPPDomainService.cs</FileName>
// <CreateTime>2017-05-16 17:44</CreateTime>
// <Author>何苗</Author>
// <Email>hemiao@woyouqiu.com</Email>
// <log date="2017-05-16 17:44" version="00001">创建</log>
// --------------------------------------------------------------
// </com.woyouqiu.Copyright>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Abp.AutoMapper;
using Abp.Configuration;
using Abp.Domain.Repositories;
using Abp.UI;
using Pingpp.Models;
using Vecen.BangChuang.BangChuang.Mall;
using Vecen.BangChuang.BangChuang.Pay;
using Vecen.BangChuang.Helpers;
using Vecen.BangChuang.Web;

namespace Vecen.BangChuang.BangChuang.DomainServices.Wallets {
    public class PingPlusPlusDomainService: BangChuangDomainServiceBase {

        private readonly IRepository<ChargeCredential, string> _chargeRepository;
        private readonly IRepository<PingppCallbackEvent, string> _callbackEventRepository;

        public PingPlusPlusDomainService(IRepository<ChargeCredential, string> chargeRepository,
            IRepository<PingppCallbackEvent, string> callbackEventRepository) {
            _chargeRepository = chargeRepository;
            _callbackEventRepository = callbackEventRepository;
        }

        /// <summary>
        /// 订单支付
        /// </summary>
        /// <param name="order"></param>
        /// <param name="channel"></param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public async Task<Charge> Pay(Order order, PingppChannel channel, string ip) {
            //正式/测试模式
            var isLive =
                await SettingManager.GetSettingValueForApplicationAsync<bool>(BangChuangConsts.SettingsName.ThirdApi
                    .ThirdApi_PingPP_LiveMode);
            //ApiKey
            var pingppApiKey = await SettingManager.GetSettingValueForApplicationAsync(isLive
                ? BangChuangConsts.SettingsName.ThirdApi.ThirdApi_PingPP_AppKey_Live
                : BangChuangConsts.SettingsName.ThirdApi.ThirdApi_PingPP_AppKey_Test);
            Pingpp.Pingpp.SetApiKey(pingppApiKey);
            //APPID
            var appId = await SettingManager.GetSettingValueForApplicationAsync(BangChuangConsts.SettingsName.ThirdApi
                .ThirdApi_PingPP_AppId);

            Pingpp.Pingpp.SetPrivateKeyPath(WebContentDirectoryFinder.CalculateContentRootFolder()
                                            + "/App_Data/pingpp_rsa_private_key.pem");

            var orderId = order.Id.ToString().PadLeft(6, '0');
            var productName = order.OrderItems.FirstOrDefault()?.ProductName;
            var body = string.Join("\n",
                order.OrderItems.Select(
                    i => $"[{i.ProductId}]{i.ProductName},{i.PriceOfTheTime}x{i.Count}={i.PriceOfTheTime * i.Count}"));
            var successUrl = string.Empty;

            var app = new Dictionary<string, string>();
            app.Add("id", appId);
            var param = new Dictionary<string, object> {
                {"order_no", orderId + DateTime.Now.ToString("yyyyMMddHHmmss")},
                {"amount", (int)(order.Price * 100)}, //支付金额，这里以“分”为单位
                {"channel", channel.ToString()}, {"currency", "cny"},
                {"subject", ($"订单号[{orderId}]{productName}").Cut(31)}, {"body", body.Cut(99)}, {"client_ip", ip},
                {"app", app}
            };

            if(new[] {"alipay_wap", "alipay_pc_direct"}.Contains(channel.ToString().ToLower())) {
                if(string.IsNullOrEmpty(successUrl)) {
                    throw new UserFriendlyException("请求失败!", "请联系系统管理员设置支付回调地址");
                }

                param.Add("extra", new Dictionary<string, string> {{"success_url", successUrl}});
            }

            var charge = await Charge.Create(param);

            var entity = charge.MapTo<ChargeCredential>();
            entity.RealOrderNo = order.Id;
            await _chargeRepository.InsertAndGetIdAsync(entity);
            return charge;
        }

        /// <summary>
        /// Ping++支付回调
        /// </summary>
        /// <param name="pingppEvent"></param>
        /// <returns></returns>
        public async Task Callback(Event pingppEvent) {
            var entity = pingppEvent.MapTo<PingppCallbackEvent>();
            await _callbackEventRepository.InsertAndGetIdAsync(entity);
        }

        /// <summary>
        /// 是否已经发起付款
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        public async Task<bool> IsHasBeenInitiatedAsync(int orderId) {
            var charge = await _chargeRepository.FirstOrDefaultAsync(c => c.RealOrderNo == orderId);
            return charge != null;
        }


        public async Task Return(OrderReturn orderReturnInfo) {
            await Refund.Create("", reParams: new Dictionary<string, object>() { });
        }
    }
}